package com.csx.base.concurrency.aqs.reentrantlock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p> what does this class do ? </p>
 *   该案例主要测试ReentrantLock除了lock,unlock,condition等方法之外的其它非核心方法
 * <p> How does it work ?</p>
 * <p> Why does it do this ?</p>
 *
 * @author cuisongxu
 * @date 2024/12/3 周二 7:36
 */
public class ReentrantLockOtherMethodTest {

    private final ReentrantLock lock = new ReentrantLock();

    private final Condition condition = lock.newCondition();

    // 入口方法
    public void test() {
        Thread thread1 = new Thread(new WaitTask(), "thread1");
        Thread thread2 = new Thread(new WaitTask(), "thread2");
        Thread thread3 = new Thread(new SampleTask(), "thread3");
        Thread thread4 = new Thread(new SampleTask(), "thread4");
        Thread thread5 = new Thread(new SampleTask(), "thread5");
        thread1.start();
        thread2.start();
        try {
            TimeUnit.MILLISECONDS.sleep(500);
            thread3.start();
            TimeUnit.MILLISECONDS.sleep(500);
            thread4.start();
            thread5.start();
            TimeUnit.MILLISECONDS.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 1. lock.getHoldCount() 获取当前线程调用 lock() 方法的次数,本质上就是重入次数
        // 2. lock.isFair() 当前锁资源是否为公平锁
        boolean fair = lock.isFair();
        // 3. lock.getQueueLength() 获取 等待获取当前锁资源的估计线程数
        int queueLength = lock.getQueueLength();
        // 4. lock.hasQueuedThread(Thread thread) 获取传入的线程是否在等待获取当前锁资源
        boolean hasQueuedThread = lock.hasQueuedThread(thread4);
        // 5. lock.hasQueuedThreads() 当前锁资源是否存在线程等待获取
        boolean hasQueuedThreads = lock.hasQueuedThreads();
        // 6. lock.isHeldByCurrentThread() 当前线程是否持有当前锁资源
        boolean heldByCurrentThread = lock.isHeldByCurrentThread();
        // 7. lock.isLocked() 当前锁资源是否被线程占用
        boolean locked = lock.isLocked();
        // 8. lock.getWaitingLength(Condition condition) 返回调用当前锁资源Condition的await对方法后未执行signal的线程估计值
        // 9. lock.hasWaiters(Condition condition) 是否有线程正在等待与此锁相关的Condition条件

        System.out.println("当前锁资源类型是否为公平锁？ " + fair);
        System.out.println("目前有 " + queueLength + " 个线程正在等待获取锁资源！");
        System.out.println(thread4.getName() + " 是否在等待获取当前锁资源？ " + hasQueuedThread);
        System.out.println("当前锁资源是否存在线程等待获取? " + hasQueuedThreads);
        System.out.println("当前线程  " + Thread.currentThread().getName() + "是否持有当前锁资源? " + heldByCurrentThread);
        System.out.println("当前锁资源是否被线程占用? " + locked);
        System.out.println("执行结束");

    }


    class WaitTask implements Runnable {

        @Override
        public void run() {
            lock.lock();
            try {
                condition.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }
    }

    class SampleTask implements Runnable {

        @Override
        public void run() {
            lock.lock();
            try {
                // 重入锁
                lock.lock();
                try {
                    // 1. lock.getHoldCount() 获取当前线程调用 lock() 方法的次数,本质上就是重入次数
                    int holdCount = lock.getHoldCount();
                    System.out.println("当前线程调用lock的次数: " + holdCount);
                    // 8. lock.getWaitingLength(Condition condition) 返回调用当前锁资源Condition的await对方法后未执行signal的线程估计值
                    int waitQueueLength = lock.getWaitQueueLength(condition);
                    System.out.println("调用condition的阻塞队列中的线程个数: " + waitQueueLength);
                    // 9. lock.hasWaiters(Condition condition) 是否有线程正在等待与此锁相关的Condition条件
                    boolean hasWaiters = lock.hasWaiters(condition);
                    System.out.println("是否有线程等待此锁condition条件? " + hasWaiters);
                    TimeUnit.SECONDS.sleep(9999);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }

            }finally {
                lock.unlock();
            }
        }
    }
    public static void main(String[] args) {
        ReentrantLockOtherMethodTest reentrantLockOtherMethodTest = new ReentrantLockOtherMethodTest();
        reentrantLockOtherMethodTest.test();
    }
}
